﻿//************************************************************************************************************
// CoNatural.dll
// Author: Roger Torres
//************************************************************************************************************
// You can use, modify, and distribute the source code and executable programs based on the source code.
// This source code is provided "as is" and without warranties as to performance or merchantability. 
// The author and/or distributors of this source code may have made statements about this source code. 
// Any such statements do not constitute warranties and shall not be relied on by the user in deciding 
// whether to use this source code. This source code is provided without any express or implied warranties 
// whatsoever. Because of the diversity of conditions and hardware under which this source code may be used, 
// no warranty of fitness for a particular purpose is offered. The user is advised to test the source code 
// thoroughly before relying on it. The user must assume the entire risk of using the source code.
//************************************************************************************************************

using System;
using System.Collections.Generic;

namespace CoNatural.Binders {
	/// <summary>
	/// Implemented by dynamic methods to bind source objects to target objects.
	/// </summary>
	/// <param name="source">The source object.</param>
	/// <param name="target">The target object.</param>
	/// <returns>The target object. When target is null, the delegate creates a new target using the default constructor and binds it to the source.</returns>
	public delegate object BinderDelegate(object source, object target);

	/// <summary>
	/// Implemented by dynamic methods to enumerate mappings from source object to target object.
	/// </summary>
	/// <param name="source">The source object (used to get indirect references.)</param>
	/// <returns>List of mappings.</returns>
	public delegate IList<IMapping> MapperDelegate(object source);

	/// <summary>
	/// Binder interface implemented by dynamic type binders
	/// </summary>
	public interface IBinder {
		BinderDelegate Bind { get; }
		MapperDelegate Map { get; }
	}

	/// <summary>
	/// Binder base class
	/// </summary>
	public class BinderBase : IBinder {
		public BinderDelegate Bind { get; private set; }
		public MapperDelegate Map { get; private set; }

		public BinderBase(BinderDelegate binder, MapperDelegate mapper) {
			Bind = binder;
			Map = mapper;
		}
	}

	/// <summary>
	/// Mapping interface implemented by mappers in type binders
	/// </summary>
	public interface IMapping {
		string Source { get; }
		string Target { get; }
		object IndirectReference { get; } // set at runtime
	}

	/// <summary>
	/// Mapping base class
	/// </summary>
	public class MappingBase : IMapping {
		public string Source { get; private set; }
		public string Target { get; private set; }
		public object IndirectReference { get; private set; } // set at runtime

		public MappingBase(string source, string target, object indirectReference) {
			Source = source;
			Target = target;
			IndirectReference = indirectReference;
		}
	}

	/// <summary>
	/// Interface implemented by BinderDelegate factories
	/// </summary>
	public interface IBinderDelegateFactory {
		/// <summary>
		/// Creates binder delegates from source to T.
		/// </summary>
		/// <param name="source">The source.</param>
		/// <param name="targetType">The target type.</param>
		/// <returns>The IBinder.</returns>
		IBinder CreateBinder(object source, Type targetType);
	}
}
